#pragma once

#include "iostream"
#include "vector"
#include "algorithm"

using namespace std;
/*HJJ QQ479287006
 *给你一个整数数组 coins ，表示不同面额的硬币；以及一个整数 amount ，表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额，返回 -1 。

你可以认为每种硬币的数量是无限的。

 

示例 1：

输入：coins = [1, 2, 5], amount = 11
输出：3
解释：11 = 5 + 5 + 1
示例 2：

输入：coins = [2], amount = 3
输出：-1
示例 3：

输入：coins = [1], amount = 0
输出：0

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * */

//完全背包问题能感觉到
int coinChange(vector<int> &coins, int amount) {

    //考虑到递推公式的特性，dp[j]必须初始化为⼀个最⼤的数，否则就会在min(dp[j - coins[i]] + 1, dp[j])⽐
    //较的过程中被初始值覆盖
    vector<int> dp(amount + 1, INT_MAX);
    dp[0] = 0;

    //先物品
    for (int i = 0; i < coins.size(); ++i) {

        for (int j = 0; j < amount + 1; ++j) {
            //
            if (j - coins[i] >= 0 && dp[j - coins[i]] != INT_MAX)
                dp[j] = min(dp[j], dp[j - coins[i]] + 1);
        }

    }
    //如果等于默认最大值表示 没有
    if (dp[amount] == INT_MAX) return -1;

    return dp[amount];

}